<?php

class ffengine1
{
	
    public /*UNUSED*/$error_log = array(), /*UNUSED*/$last_error = "";
    //changed from logging error & return false, to "throw a friggin exception whenever stuff happens"
    protected $dbname=null;//please use connect() instead
    protected $sql_username, $sql_password, $sql_host; //currently unused..
    private $__connected = false; //use is_connected() instead please
    function __construct()
    {
    }
    
    function __destruct()
    {
    }
	/*
	 * usage: connect(host,username,password,databasename[,port=3306[,socket=null]])
	 * returns: true. 
	 * (the alternative is to throw an exception, either with $this->err() OR PDOexception...)
	 * 
	 */
    public function connect($host, $username, $password, $databasename, $port =3306,$socket=null)
    {
		$debugstr='connect('.$this->myretvardump($host).','.$this->myretvardump($username).','.'***PASSWORD_CENSORED***'.','.$this->myretvardump($databasename).','.$this->myretvardump($port).'): ';
    	if (empty($port)){
    	$this->err($debugstr.' needs a port!',true);
    	}
    	if(empty($databasename)){
    		$this->err($debugstr.' needs a databasename!',true);
    	}
		if(empty($username))
		{
		$this->err($debugstr.' needs a database username!',true);
		}
    	$this->dbname=$databasename;
    	$this->pdo=new PDO('mysql:host='.$host.';dbname='.$databasename.';port='.$port,$username,$password);
    	$this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
		$this->__connected = true;
    	return true;
    }
    
    /*
	 * used allot internally to handling internal errors
	 * (and by "handling interal errors", i mean "throws exceptions")
	 */
    private function err(/*mixed(string/array)*/$info,/*boolean*/$fatal=true)
    {
//        throw new Exception('ffengine1::err('.$this->myretvardump(func_get_args()).') was called! stack trace for more info..');
        throw new Exception('ffengine1::err(...) was called! stack trace for more info..');
        die();return; ///DEPRECATED CODE BELOW...
    }
    
    
    /*
     *use this function to check if you're currently connected to a database
     *returns (bool)true/false
	 */
    public function is_connected()
    {
		if(!is_a($this->pdo,"PDO",true) || !$this->__connected)
		{
			return false;
		}
		try{
		if($this->pdo->query('SELECT NULL')===false){return false;}
		return true;
		} catch(PDOException $e){return false;}
		return false;//unreachable (almost)
    }
	/*
	 * returns var_dump(...) output as a string
	 */
    public static function myretvardump()
    {
        ob_start();
        $args = func_get_args();
        call_user_func_array('var_dump', $args);
        return ob_get_clean();
    }
	/*
	 *basically an alias for var_dump(...)
	 */
	public static function dump(/*...*/)
	{
       $args = func_get_args();
	   if(is_callable('xdebug_var_dump')){
		call_user_func_array('xdebug_var_dump', $args);			
		}else{
		call_user_func_array('var_dump', $args);			
		}
	}

    
    /*
	 * usage: getFileChunkIDs(id)
	 * returns array([0=array('chunk_id'=>id,'debuginfo_chunksize_bytes'=>bytes)[,1=array('chunk_id'=>id,'debuginfo_chunksize_bytes'=>bytes)[,2=array('chunk_id'=>id,'debuginfo_chunksize_bytes'=>bytes)[,...]]]])
	 * returns empty array if fullFileID does not exist.
	 * calls $this->err() when something bad happens
     */
    public function getFileChunkIDs($fullFileID)
    {
		$debugstr='getFileChunkIDs('.$this->myretvardump($fullFileID).'): ';
        $debug = false;
		//$debug = true;
        if (!$this->is_connected()) {
            $this->err($debugstr.' must be connected!');
            return false;
        }
        $query = 'SELECT ';
        if ($debug) {
            $query .= ' `files_chunks_associations`.`id` AS `id`';
            $query .= ', `files_chunks_associations`.`complete_files_id` AS `complete_files_id`';
            $query .= ', `files_chunks_associations`.`chunk_id` AS `chunk_id`';
            $query .= ', `files_chunks_associations`.`chunk_sort_number` AS `chunk_sort_number`';
            $query .= ', `files_chunks_associations`.`debuginfo_upload_datetime` AS `debuginfo_upload_datetime`';
            $query .= ', `files_chunks_associations`.`debuginfo_chunksize_bytes` AS `debuginfo_chunksize_bytes`';
            $query .= ', `files_chunks_associations`.`debuginfo_original_owner_id` AS `debuginfo_original_owner_id`';
            $query .= ', `files_chunks_associations`.`debuginfo_original_filename` AS `debuginfo_original_filename`';
            $query .= ', `files_chunks_associations`.`debuginfo_extra_notes` AS `debuginfo_extra_notes`';            
        } else/*if(!$debug)*/{
        $query.='`files_chunks_associations`.`chunk_id` AS `chunk_id`';
        /*TODO: is this needed/interesting here?*/ 
		$query .= ', `files_chunks_associations`.`debuginfo_chunksize_bytes` AS `debuginfo_chunksize_bytes`';
        }
        $query .= ' FROM `files_chunks_associations`';
        $query .= ' WHERE `files_chunks_associations`.`complete_files_id` = ' . $this->pdo->quote($fullFileID) . ' ';
        $query .= ' ORDER BY `files_chunks_associations`.`chunk_sort_number` ASC';
        $PDOStatementH=$this->pdo->query($query);
		$res=$PDOStatementH->fetchAll(PDO::FETCH_BOTH);
		//var_dump($query,$PDOStatementH,$res);
		if(!is_array($res)){
			$this->err($debugstr.' got unexpected result from database..1',true);
		}
		$ret=array();
		foreach($res as $key=>$a)
		{
			if(!is_array($a)){
				$this->err($debugstr.' got unexpected result from database..2',true);
			}
			if(empty($a['chunk_id'])){
			$this->err($debugstr.' got unexpected result from database..3',true);				
			}
			if(empty($a['debuginfo_chunksize_bytes']) || !preg_match("/^[0-9]+$/",$a['debuginfo_chunksize_bytes']))
			{
				$this->err($debugstr.' got unexpected result from database..4',true);								
			}
//		$ret[$a['chunk_id']]=$a['debuginfo_chunksize_bytes'];
		$ret[]=array('chunk_id'=>$a['chunk_id'],'debuginfo_chunksize_bytes'=>$a['debuginfo_chunksize_bytes']);
		}
		return $ret;
    }
	
	/*
	 * Usage: getFileInfo(array([id[,id[,id[,...]]]]))
	 * output: array([id=>info[,id=>info[,id=>info[,...]]]]);
	 * if id does not exist, info is bool(false),
	 * if id does exist, info is: array(
	 * 'owner_id'=>string('X'),
	 * 'filesize_bytes'=>int(X),
	 * 'filename'=>string('filename'),
	 * 'fullfile_sha256'=>string('ABCDEFG'),
	 * 'upload_datetime'=>string('1970-00-00 00:00:00'),
	 * 'requireAUTH'=>bool(true/false)
	 *);
	 * calls $this->err() if anything bad happens
	 */
	public function getFileInfo($fullFileIDArray)
	{
	$debug=false;
	$debugstr='getFileInfo('.$this->myretvardump($fullFileIDArray).'):';
	//$debug=true;
    if (!$this->is_connected()) {
		$this->err($debugstr.' must be connected!');
            return false;
        }
	if(!is_array($fullFileIDArray)){
	$this->err($debugstr.' argv[0] must be an array! (even if empty array)');
	return false;
	}
	if(empty($fullFileIDArray)){return array();}
	$tmpArr=array();
	foreach($fullFileIDArray as $val)
	{
		$tmpArr[$val]=false;//this will be owerwritten with info from database (if any)
	}
	$fullFileIDArray=$tmpArr;
	unset($tmpArr);
	$query='SELECT ';
	$query.='`complete_files`.`owner_id` AS `owner_id`';
	$query.=', `complete_files`.`filesize_bytes` AS `filesize_bytes`';
	$query.=', `complete_files`.`filename` AS `filename`';
	$query.=', `complete_files`.`fullfile_sha256` AS `fullfile_sha256`';
	$query.=', `complete_files`.`upload_datetime` AS `upload_datetime`';
	$query.=', `complete_files`.`requireAUTH` AS `requireAUTH`';
	$query.=', `complete_files`.`id` AS `id`';
	if($debug){
	$query.=', `complete_files`.`debuginfo_upload_ip` AS `debuginfo_upload_ip`';
	$query.=', `complete_files`.`debuginfo_extra_notes` AS `debuginfo_extra_notes`';
	}
	$query.=' FROM `complete_files`';
//	$query.=' WHERE `complete_files`.`id` = '.$this->pdo->quote($fullFileID).'';
	$query.=' WHERE `complete_files`.`id` IN (';
	//we already know $fullFileIDArray is an array and is NOT empty.
	foreach($fullFileIDArray as $key=>$unused)
	{
		$query.=$this->pdo->quote($key);
		$query.=',';
	}
	unset($key,$unused);
	$query=substr($query,0,strlen($query)-1);//remove the last comma... I wonder if theres  a better way to make this query :p
	$query.=')';
	$PDOStatementH=$this->pdo->query($query);
	$res=$PDOStatementH->fetchAll();
	//var_dump($query,$PDOStatementH,$res);
	$ret=$fullFileIDArray;//
	foreach($res as $key=>$val)
	{
	if(!is_array($val)){$this->err($debugstr.' got unexpected result from database..1',true);}
	if(empty($val['filesize_bytes']) || !preg_match('/^[0-9]+$/', $val['filesize_bytes'])){$this->err($debugstr.' got unexpected result from database..2',true);}
	if(empty($val['filename'])){$this->err($debugstr.' got unexpected result from database..3',true);}
	if(empty($val['fullfile_sha256'])){$this->err($debugstr.' got unexpected result from database..4',true);}
	if(!isset($val['requireAUTH'])/*BTW: 0 is considdered empty -.-*/){$this->err($debugstr.' got unexpected result from database..5',true);}
	if(!isset($FullFileIDArray[$val['id']])){$this->err($debugstr.' got unexpected result from database..6',true);}
	$id=$val['id'];
	if(/*!is_array($ret[$id])*/$ret[$id]===false){$ret[$id]=array();}
		$ret[$id]['owner_id']=$val['owner_id'];
		$ret[$id]['filesize_bytes']=(int)$val['filesize_bytes'];
		$ret[$id]['filename']=$val['filename'];
		$ret[$id]['fullfile_sha256']=$val['fullfile_sha256'];
		$ret[$id]['upload_datetime']=$val['upload_datetime'];
		$ret[$id]['requireAUTH']=(bool)$val['requireAUTH'];
		if($debug){
		$ret[$id]['id']=$val['id'];//===$id
		$ret[$id]['debuginfo_upload_ip']=$val['debuginfo_upload_ip'];
		$ret[$id]['debuginfo_extra_notes']=$val['debuginfo_extra_notes'];
		}
	}
	return $ret;
	}

	
    
	
	
    public function testengine()
    {
        return $this->d();
    }
    //debug/development function...
    public function d()
    {
	$df=function($query){
	$PDOStatementH=$this->pdo->query($query);
	$res=$PDOStatementH->fetchAll();
	
    echo htmlentities($query.': '.$this->myretvardump($PDOStatementH,$res)); 
	};
    
    $df('SELECT * FROM `users` WHERE 1');
    $df('SELECT * FROM `complete_files` WHERE 1');
    $df('SELECT * FROM `files_chunks_associations` WHERE 1');
	$df('SELECT * FROM `file_chunks` WHERE 1');
	$df('SELECT * FROM `harddrives` WHERE 1');
	$df('SELECT * FROM `local_disk` WHERE 1');
    $df('SELECT * FROM `ftp_disks` WHERE 1');
	$df('SELECT * FROM `webdav_disks` WHERE 1');
    $df('SELECT * FROM `mysql_blob_disks` WHERE 1');
	$df('SELECT * FROM `http_disks` WHERE 1');
    //echo '$sqlh->warning_count: ', $this->sqlh->warning_count;
        
    } //end of public function d()
    
} //end of class ffengine1